package coffeerush.organizer.mail;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.search.FlagTerm;

/**
 * Класс для получения/отправления/удаления простых электронных писем, а также 
 * электронных писем с вложениями, с указанного почтового ящика.
 * @author Ryzhko Oleg 
 */
public class MailServer {
    
    private static final String ENCODING = "UTF-8";
    private static String _smtpHost = "smtp.google.com";
    private static String _pop3Host = "pop3.google.com";
    private static String _smtpPort = "465";
    private static String _imapHost = "imap.google.com";
    private static String _user = "ryz.oleg@gmail.com";
    private static String _pass = "phieR4ith7";
    private static String _from = "ryz.oleg@gmail.com";
    
    
    public static void sendMessage(String user, String password, String from,
                                String to, String subject, String content, 
                                String smtpHost, String smtpPort) throws MessagingException,
                                                                         UnsupportedEncodingException{
        Properties props = System.getProperties();
        props.put("mail.smtp.port", _smtpPort);
        props.put("mail.smtp.host", _smtpHost);
        props.put("mail.smtp.auth", "true");
        props.put("mail.mime.charset", ENCODING);
        
        Authenticator auth = new UserMailAuthenticator(user, password);
        Session session = Session.getDefaultInstance(props, auth);
        
        Message msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(from));
        msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
        msg.setSubject(subject);
        msg.setText(content);
        Transport.send(msg);
    }
    
    public static void sendMessage(String user, String password, String from,
                                String to, String subject, String content, String attachment,
                                String smtpHost, String smtpPort) throws MessagingException,
                                                                         UnsupportedEncodingException{
        
        Properties props = System.getProperties();
        props.put("mail.smtp.port", _smtpPort);
        props.put("mail.smtp.host", _smtpHost);
        props.put("mail.smtp.auth", "true");
        props.put("mail.mime.charset", ENCODING);
        
        Authenticator auth = new UserMailAuthenticator(user, password);
        Session session = Session.getDefaultInstance(props, auth);
        
        Message msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress(from));
        msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
        msg.setSubject(subject);
        
        BodyPart msgBodyPart = new MimeBodyPart();
        msgBodyPart.setContent(content, "text/plain; charset="+ENCODING+"");
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(msgBodyPart);
        
        MimeBodyPart attachmentBodyPart = new MimeBodyPart();
        DataSource source = new FileDataSource(attachment);
        attachmentBodyPart.setDataHandler(new DataHandler(source));
        attachmentBodyPart.setFileName(MimeUtility.encodeText(source.getName()));
        multipart.addBodyPart(attachmentBodyPart);
        msg.setContent(multipart);
        Transport.send(msg);
        
    }
    
    public static LinkedList<MessageBean> getMessages(String user, String password, String host) throws MessagingException, IOException{
        
        Authenticator auth = new UserMailAuthenticator(user, password);

        Properties props = System.getProperties();
        props.put("mail.user", user);
        props.put("mail.host", host);
        props.put("mail.debug", "false");
        props.put("mail.store.protocol", "pop3");
        props.put("mail.transport.protocol", "smtp");

        Session session = Session.getDefaultInstance(props, auth);
        Store store = session.getStore();
        store.connect();
        Folder inbox = store.getFolder("INBOX");
        inbox.open(Folder.READ_WRITE);

        Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
        ArrayList<String> attachments = new ArrayList<String>();

        LinkedList<MessageBean> listMessages = getPart(messages, attachments);

        inbox.setFlags(messages, new Flags(Flags.Flag.SEEN), true);
        inbox.close(false);
        store.close();
        return listMessages;
    }
    
    private static LinkedList<MessageBean> getPart(Message[] messages, ArrayList<String> attachments) throws MessagingException, IOException {
        LinkedList<MessageBean> listMessages = new LinkedList<MessageBean>();
        SimpleDateFormat f = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
        for (Message inMessage : messages) {
            attachments.clear();
            if (inMessage.isMimeType("text/plain")) {
                
                MessageBean message = new MessageBean(MimeUtility.decodeText(inMessage.getSubject()), 
                                                      inMessage.getFrom()[0].toString(), null,
                                                      f.format(inMessage.getSentDate()), (String) inMessage.getContent(),
                                                      false, inMessage.getMessageNumber(), null);
                listMessages.add(message);
            } 
            else if (inMessage.isMimeType("multipart/*")) {
                
                Multipart mp = (Multipart) inMessage.getContent();
                MessageBean message = null;
                
                for (int i = 0; i < mp.getCount(); i++) {
                    
                    Part part = mp.getBodyPart(i);
                    if ((part.getFileName() == null || part.getFileName().isEmpty()) && part.isMimeType("text/plain")) {
                        message = new MessageBean( inMessage.getSubject(), inMessage.getFrom()[0].toString(),
                                                   null, f.format(inMessage.getSentDate()), (String) part.getContent(),
                                                   false, inMessage.getMessageNumber(), null);
                    } 
                    else if (part.getFileName() != null || part.getFileName().isEmpty()){
                        if ((part.getDisposition() != null) && (part.getDisposition().equals(Part.ATTACHMENT))) {
                            attachments.add(saveFile(MimeUtility.decodeText(part.getFileName()), part.getInputStream()));
                            if (message != null) {
                                message.setAttachments(attachments);
                            }
                        }
                    }
                }
                listMessages.add(message);
            }
        }
        return listMessages;
    }
    
    public static void deleteMessage(String user, String password, String host, int n) throws MessagingException, IOException{
        
        Authenticator auth = new UserMailAuthenticator(user, password);
        Properties props = System.getProperties();
        props.put("mail.user", user);
        props.put("mail.host", host);
        props.put("mail.debug", "false");
        props.put("mail.store.protocol", "pop3");
        props.put("mail.transport.protocol", "smtp");
        
        Session session = Session.getDefaultInstance(props, auth);
        Store store = session.getStore();
        store.connect();
        Folder inbox = store.getFolder("INBOX");
        inbox.open(Folder.READ_WRITE);

        inbox.setFlags(n, n, new Flags(Flags.Flag.DELETED), true);
        inbox.close(true);
        store.close();
        
    }

    private static String saveFile(String filename, InputStream input) {
        String path = "attachments\\"+filename;
        try {
            byte[] attachment = new byte[input.available()];
            input.read(attachment);
            File file = new File(path);
            FileOutputStream out = new FileOutputStream(file);
            out.write(attachment);
            input.close();
            out.close();
            return path;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return path;
    }
}
